#!/bin/bash
#
# This script can be used to interact with opensd via ansible.

function find_base_dir {
    local real_path=$(python -c "import os;print(os.path.realpath('$0'))")
    local dir_name="$(dirname "$real_path")"
    if [ -z "$SNAP" ]; then
        if [[ ${dir_name} == "/usr/bin" ]]; then
            BASEDIR=/usr/share/opensd
        elif [[ ${dir_name} == "/usr/local/bin" ]]; then
            BASEDIR=/usr/local/share/opensd
        elif [[ -n ${VIRTUAL_ENV} ]] && [[ ${dir_name} == "${VIRTUAL_ENV}/bin" ]]; then
            BASEDIR="${VIRTUAL_ENV}/share/opensd"
        else
            BASEDIR="$(dirname ${dir_name})"
        fi
    else
        BASEDIR="$SNAP/share/opensd"
    fi
}

function process_cmd {
    echo "$ACTION : $CMD"
    $CMD
    if [[ $? -ne 0 ]]; then
        echo "Command failed $CMD"
        exit 1
    fi
}

function usage {
    cat <<EOF
Usage: $0 COMMAND [options]

Options:
    --inventory, -i <inventory_path>   Specify path to ansible inventory file
    --playbook, -p <playbook_path>     Specify path to ansible playbook file
    --key -k <key_path>                Specify path to ansible vault keyfile
    --help, -h                         Show this usage information
    --tags, -t <tags>                  Only run plays and tasks tagged with these values
    --skip-tags <tags>                 Only run plays and tasks whose tags do not match these values
    --extra, -e <ansible variables>    Set additional variables as key=value or YAML/JSON passed to ansible-playbook
    --passwords <passwords_path>       Specify path to the passwords file
    --limit <host>                     Specify host to run plays
    --forks <forks>                    Number of forks to run Ansible with
    --vault-id <@prompt or path>       Specify @prompt or password file (Ansible >=  2.4)
    --ask-vault-pass                   Ask for vault password
    --vault-password-file <path>       Specify password file for vault decrypt
    --verbose, -v                      Increase verbosity of ansible-playbook

Commands:
    prechecks           Do pre-deployment checks for hosts
    postchecks          Do post-deployment checks for hosts
    mariadb_recovery    Recover a completely stopped mariadb cluster
    bootstrap   Bootstrap servers with opensd deploy dependencies
    deploy              Deploy and start all openstack services
    compute_extend      Extend openstack compute nodes
EOF
}

function bash_completion {
cat <<EOF
--inventory -i
--playbook -p
--configdir
--key -k
--help -h
--skip-tags
--tags -t
--extra -e
--passwords
--limit
--forks
--vault-id
--ask-vault-pass
--vault-password-file
--verbose -v
prechecks
postchecks
mariadb_recovery
bootstrap
deploy
compute_extend
EOF
}

SHORT_OPTS="hi:p:t:k:e:v"
LONG_OPTS="help,inventory:,playbook:,skip-tags:,tags:,key:,extra:,verbose,configdir:,passwords:,limit:,forks:,vault-id:,ask-vault-pass,vault-password-file:,yes-i-really-really-mean-it,include-images,include-dev"

RAW_ARGS="$*"
ARGS=$(getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" --name "$0" -- "$@") || { usage >&2; exit 2; }

eval set -- "$ARGS"

find_base_dir

INVENTORY="${BASEDIR}/ansible/inventory/all-in-one"
PLAYBOOK="${BASEDIR}/ansible/site.yml"
VERBOSITY=
EXTRA_OPTS=${EXTRA_OPTS}
CONFIG_DIR="/etc/opensd"
PASSWORDS_FILE="${CONFIG_DIR}/passwords.yml"
DANGER_CONFIRM=
INCLUDE_IMAGES=
INCLUDE_DEV=
# Serial is not recommended and disabled by default. Users can enable it by
# configuring ANSIBLE_SERIAL variable.
ANSIBLE_SERIAL=${ANSIBLE_SERIAL:-0}

while [ "$#" -gt 0 ]; do
    case "$1" in

    (--inventory|-i)
            INVENTORY="$2"
            shift 2
            ;;

    (--playbook|-p)
            PLAYBOOK="$2"
            shift 2
            ;;

    (--skip-tags)
            EXTRA_OPTS="$EXTRA_OPTS --skip-tags $2"
            shift 2
            ;;

    (--tags|-t)
            EXTRA_OPTS="$EXTRA_OPTS --tags $2"
            shift 2
            ;;

    (--verbose|-v)
            VERBOSITY="$VERBOSITY --verbose"
            shift 1
            ;;

    (--configdir)
            CONFIG_DIR="$2"
            shift 2
            ;;

    (--yes-i-really-really-mean-it)
            if [[ ${RAW_ARGS} =~ "$1" ]]
            then
                DANGER_CONFIRM="$1"
            fi
            shift 1
            ;;

    (--include-images)
            INCLUDE_IMAGES="$1"
            shift 1
            ;;

    (--include-dev)
            INCLUDE_DEV="$1"
            shift 1
            ;;

    (--key|-k)
            VAULT_PASS_FILE="$2"
            EXTRA_OPTS="$EXTRA_OPTS --vault-password-file=$VAULT_PASS_FILE"
            shift 2
            ;;

    (--extra|-e)
            EXTRA_OPTS="$EXTRA_OPTS -e $2"
            shift 2
            ;;

    (--passwords)
            PASSWORDS_FILE="$2"
            shift 2
            ;;

    (--limit)
            EXTRA_OPTS="$EXTRA_OPTS --limit $2"
            shift 2
            ;;

    (--forks)
            EXTRA_OPTS="$EXTRA_OPTS --forks $2"
            shift 2
            ;;

    (--vault-id)
            EXTRA_OPTS="$EXTRA_OPTS --vault-id $2"
            shift 2
            ;;

    (--ask-vault-pass)
            VERBOSITY="$EXTRA_OPTS --ask-vault-pass"
            shift 1
            ;;

    (--vault-password-file)
            EXTRA_OPTS="$EXTRA_OPTS --vault-password-file $2"
            shift 2
            ;;

    (--help|-h)
            usage
            shift
            exit 0
            ;;

    (--)
            shift
            break
            ;;

    (*)
            echo "error"
            exit 3
            ;;
esac
done

case "$1" in

(prechecks)
        ACTION="Pre-deployment checking"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=precheck"
        ;;
(postchecks)
        ACTION="Post-deployment checking"
        PLAYBOOK="${BASEDIR}/ansible/postchecks.yml"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=postcheck"
        ;;
(mariadb_recovery)
        ACTION="Attempting to restart mariadb cluster"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=deploy -e common_run=true"
        PLAYBOOK="${BASEDIR}/ansible/mariadb_recovery.yml"
        ;;
(bootstrap)
        ACTION="Bootstraping servers"
        PLAYBOOK="${BASEDIR}/ansible/opensd-host.yml"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=bootstrap"
        ;;
(deploy)
        ACTION="Deploying Playbooks"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=deploy"
        ;;
(compute_extend)
        ACTION="Extend compute nodes"
        PLAYBOOK="${BASEDIR}/ansible/compute_extend.yml"
        EXTRA_OPTS="$EXTRA_OPTS -e opensd_action=compute_extend"
        ;;
(bash-completion)
        bash_completion
        exit 0
        ;;
(*)     usage
        exit 0
        ;;
esac

CONFIG_OPTS="-e @${CONFIG_DIR}/globals.yml -e @${PASSWORDS_FILE} -e CONFIG_DIR=${CONFIG_DIR}"
CMD="ansible-playbook -i $INVENTORY $CONFIG_OPTS $EXTRA_OPTS $PLAYBOOK $VERBOSITY"
process_cmd
